#include "hrvas.h"
#include "ui_hrvas.h"
#include "shareAlg/arrayOper/outlierdetector.h"
#include "shareAlg/arrayOper/replaceoutliers.h"
#include "shareAlg/arrayOper/arrayoperation.h"
#include "HRVAna/hrv_timecompute.h"

HRVAs::HRVAs(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::HRVAs)
{
    ui->setupUi(this);
    initQcustomPlots();
    //initData();
    initControls();

}

HRVAs::~HRVAs()
{
    delete ui;
}

void HRVAs::initControls()
{
    ui->radioButton_EctopicRep_None->setChecked(true);
    ui->lineEdit_EctopicD_p->setValidator(new QIntValidator(1,20,this));
    ui->lineEdit_EctopicD_std->setValidator(new QIntValidator(1,20,this));
    ui->lineEdit_EctopicD_median->setValidator(new QIntValidator(1,20,this));
    ui->lineEdit_EctopicRep_mean->setValidator(new QIntValidator(1,20,this));
    ui->lineEdit_EctopicRep_median->setValidator(new QIntValidator(1,20,this));
    ui->radioButton_fft->setChecked(true);
}
void HRVAs::initQcustomPlots()
{
    initRRCurve();
}

void HRVAs::initRRCurve()
{
    QCPGraph *graph = ui->widget_RR->addGraph();
    graph->setLineStyle(QCPGraph::lsNone); // 启用线条连接
    graph->setScatterStyle(QCPScatterStyle::ssCircle); // 设置点的样式为圆圈
    ui->widget_RR->graph(0)->setPen(QPen(Qt::blue)); // 设置初始曲线颜色
    ui->widget_RR->graph(0)->setName("RR间期");
    // 启用图例
    ui->widget_RR->legend->setVisible(true);
    // 调整图例大小
    ui->widget_RR->legend->setAntialiased(true);
    // ui->widget_RR->legend->setMinimumSize(150,  50); // 设置最小尺寸
    // ui->widget_RR->legend->setMaximumSize(200,  100); // 设置最大尺寸
    // 设置字体大小
    QFont legendFont = ui->widget_RR->legend->font();
    legendFont.setPointSize(10);  // 设置字体大小为 12
    ui->widget_RR->legend->setFont(legendFont);
    // 设置图表名称
    QCPTextElement *title = new QCPTextElement(ui->widget_RR); // 创建标题元素
    title->setText("RR间期时域波形图");                              // 设置标题文本
    title->setFont(QFont("sans", 12, QFont::Bold));         // 设置字体
    ui->widget_RR->plotLayout()->insertRow(0);                   // 在顶部插入一行
    ui->widget_RR->plotLayout()->addElement(0,  0, title);        // 将标题添加到布局中
    // 将图例放到图表右侧外面
    // 创建一个新的QCPLayoutGrid来放置图例
    QCPLayoutGrid* subLayout = new QCPLayoutGrid;
    ui->widget_RR->plotLayout()->addElement(2, 0, subLayout); // 将subLayout添加到主布局的指定位置
    // 设置subLayout的边距
    subLayout->setMargins(QMargins(0, 0, 1000, 5));
    // 将图例添加到subLayout中
    subLayout->addElement(0, 0, ui->widget_RR->legend);
    // 调整图例的填充顺序（可选）
    ui->widget_RR->legend->setFillOrder(QCPLegend::foColumnsFirst);
    // 设置图例所在行的拉伸因子，以控制其高度
    ui->widget_RR->plotLayout()->setRowStretchFactor(2, 0.001);
    // 重绘图表以显示更改
    ui->widget_RR->replot();
    // 启用交互功能
    ui->widget_RR->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
    ui->widget_RR->setSelectionRectMode(QCP::SelectionRectMode::srmZoom);
    // ui->widget_RR->setInteraction(QCP::iRangeDrag, true);
    ui->widget_RR->setNoAntialiasingOnDrag(true);
    // 设置坐标轴标签
    ui->widget_RR->xAxis->setLabel("Time(S)");
    ui->widget_RR->yAxis->setLabel("ms");
    ui->widget_RR->yAxis->setRange(400, 1400);

    //两根标准差线
    ui->widget_RR->addGraph();
    ui->widget_RR->graph(1)->setName("均值+3倍标准差");
    QPen pen;
    pen.setStyle(Qt::DashLine);  // 设置为虚线
    pen.setColor(Qt::red);      // 设置线条颜色
    pen.setWidth(1);             // 设置线条宽度

    ui->widget_RR->graph(1)->setPen(pen); // 设置初始曲线颜色
    ui->widget_RR->addGraph();
    ui->widget_RR->graph(2)->setPen(pen); // 设置初始曲线颜色
    ui->widget_RR->graph(2)->setName("均值-3倍标准差");
    //异常点
    QCPGraph *graph2 = ui->widget_RR->addGraph();
    graph2->setLineStyle(QCPGraph::lsNone); // 启用线条连接
    graph2->setScatterStyle(QCPScatterStyle::ssCircle); // 设置点的样式为圆圈
    ui->widget_RR->graph(3)->setPen(QPen(Qt::red,2)); // 设置初始曲线颜色
    ui->widget_RR->graph(3)->setName("异常rr间期");

}
void HRVAs::on_pushButton_exit_clicked()
{
    this->close();
}


void HRVAs::on_pb_TimeDomain_clicked()
{
    ui->tabWidget->setCurrentIndex(0);
}


void HRVAs::on_pb_FreqDomain_clicked()
{
    ui->tabWidget->setCurrentIndex(1);
}


void HRVAs::on_pb_Scatter_clicked()
{
    ui->tabWidget->setCurrentIndex(2);
}


void HRVAs::on_pb_NonLinearDomain_clicked()
{
    ui->tabWidget->setCurrentIndex(3);
}


void HRVAs::on_pb_TimeFreqDomain_clicked()
{
    ui->tabWidget->setCurrentIndex(4);
}


void HRVAs::on_pb_MentalPressure_clicked()
{
    ui->tabWidget->setCurrentIndex(5);
}


void HRVAs::on_pb_Nerval_clicked()
{
    ui->tabWidget->setCurrentIndex(6);
}

/**
 * @brief HRVAs::initData
 * 初始化数据
 */
void HRVAs::initData()
{
    ui->pb_ectopicCheck->setEnabled(true);
    rawRRData_x.clear();
    rawRRData_y.clear();
    // rawRRData_y=readLinesToVector("E:/qtCode/heart-language-laboratory/TestMatlabLib/TestMatlabLib/nibi.txt");
    readtxtFile("E:/qtCode/heart-language-laboratory/TestMatlabLib/TestMatlabLib/nibi.txt",rawRRData_x,rawRRData_y);
    // QList<double> xData, yData;
    if (!readtxtFile("E:/qtCode/heart-language-laboratory/TestMatlabLib/TestMatlabLib/nibi.txt",  rawRRData_x, rawRRData_y)) {
        // 处理错误
    } else {
        // 使用数据...
        rawrr_Len=rawRRData_y.size();
        qDebug()<<"rawrr_Len="<<rawrr_Len;
        // rawRRData_x.clear();
        // for(int i=0;i<rawrr_Len;i++)
        //     rawRRData_x.append(i);

        UpdateRRGraph(rawRRData_x,rawRRData_y);
    }


}
void HRVAs::UpdateRRGraph(QVector<double>x,QVector<double>y)
{
    int len=x.size();
    qDebug()<<"len="<<len;
    ui->widget_RR->graph(0)->setData(x,y);
    ui->widget_RR->xAxis->setRange(0,x.at(x.size()-1));
    double meanRR=ArrayOperation::instance().calculateMean(y);
    double stdRR=ArrayOperation::instance().calculateStdDev(y);
    QVector<double>m_std_low_x,m_std_up_x,m_std_low_y,m_std_up_y;
    m_std_low_x.append(0);m_std_low_x.append(x.at(x.size()-1));
    m_std_up_x.append(0);m_std_up_x.append(x.at(x.size()-1));
    m_std_low_y.append(meanRR-3*stdRR);m_std_low_y.append(meanRR-3*stdRR);
    m_std_up_y.append(meanRR+3*stdRR);m_std_up_y.append(meanRR+3*stdRR);
    ui->widget_RR->graph(1)->setData(m_std_low_x,m_std_low_y);
    ui->widget_RR->graph(2)->setData(m_std_up_x,m_std_up_y);
    // 刷新图表
    ui->widget_RR->removeGraph(3);
    QCPGraph *graph2 = ui->widget_RR->addGraph();
    graph2->setLineStyle(QCPGraph::lsNone); // 启用线条连接
    graph2->setScatterStyle(QCPScatterStyle::ssCircle); // 设置点的样式为圆圈
    ui->widget_RR->graph(3)->setPen(QPen(Qt::red,2)); // 设置初始曲线颜色
    ui->widget_RR->graph(3)->setName("异常rr间期");
    ui->widget_RR->replot();
}
void HRVAs::on_pushButton_run_clicked()
{
    initData();
}

QVector<double> HRVAs::readLinesToVector(const QString &filePath) {
    QVector<double> lines; // 用于存储每一行的QVector
    QFile file(filePath);   // 打开文件

    if (file.open(QIODevice::ReadOnly  | QIODevice::Text)) {
        QTextStream in(&file); // 创建文本流
        while (!in.atEnd())  {  // 逐行读取文件
            QString line = in.readLine();  // 读取一行
            lines.append(line.toInt()*4);  // 将行添加到QVector中
        }
        file.close();  // 关闭文件
    } else {
        qWarning() << "无法打开文件：" << filePath;
    }

    return lines;
}

/**
 * @brief 从文本文件读取两列数据到输出列表（优化版）
 * @param filePath 文件路径
 * @param[out] x 存储第一列数据的输出列表
 * @param[out] y 存储第二列数据的输出列表
 * @return 是否成功读取
 */
bool HRVAs::readtxtFile(const QString &filePath, QList<double>& x, QList<double>& y)
{
    // 清空输出列表以确保数据纯净
    x.clear();
    y.clear();

    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly  | QIODevice::Text)) {
        qWarning() << "无法打开文件:" << filePath
                   << "错误:" << file.errorString();
        return false;
    }

    QTextStream in(&file);
    int lineNumber = 0;
    bool hasError = false;

    while (!in.atEnd())  {
        lineNumber++;
        QString line = in.readLine().trimmed();

        // 跳过空行和注释行（以#开头）
        if (line.isEmpty()  || line.startsWith('#'))  {
            continue;
        }

        // 使用正则表达式分割可能包含空格的CSV数据
        QStringList columns = line.split(QRegularExpression("\\s*,\\s*"),  Qt::SkipEmptyParts);

        // 验证数据列数
        if (columns.size()  != 2) {
            qWarning() << "第" << lineNumber << "行数据格式错误，需要两列数据"
                       << "实际内容:" << line;
            hasError = true;
            continue;
        }

        // 转换数据并验证有效性
        bool ok1, ok2;
        double val1 = columns[0].toDouble(&ok1);
        double val2 = columns[1].toDouble(&ok2)*1000;

        if (!ok1 || !ok2) {
            qWarning() << "第" << lineNumber << "行包含非数值数据"
                       << "内容:" << line;
            hasError = true;
            continue;
        }

        x.append(val1);
        y.append(val2);
    }

    file.close();

    // 验证是否读取到有效数据
    if (x.isEmpty())  {
        qWarning() << "文件未包含有效数据:" << filePath;
        return false;
    }

    qDebug() << "成功读取" << x.size()  << "条数据 from:" << filePath;
    return !hasError;
}
/**
 * @brief HRVAs::on_pb_ectopicCheck_clicked
 * 异常rr检测
 */
void HRVAs::on_pb_ectopicCheck_clicked()
{
    bool b_p=ui->checkBox_EctopicD_p->isChecked();
    bool b_sd=ui->checkBox_EctopicD_std->isChecked();
    bool b_median=ui->checkBox_EctopicD_median->isChecked();
    Ectopic_b.clear();
    if(b_p || b_sd ||b_median){
        OutlierDetector detector;
        QVector<bool> outliers_p(rawrr_Len,  false);
        QVector<bool> outliers_median(rawrr_Len,  false);
        QVector<bool> outliers_sd(rawrr_Len,  false);
        if(b_p)
            outliers_p = detector.locateOutliers(rawRRData_x,  rawRRData_y, "percent", ui->lineEdit_EctopicD_p->text().toDouble());

        if(b_sd)
            outliers_sd=detector.locateOutliers(rawRRData_x,rawRRData_y,"sd",ui->lineEdit_EctopicD_std->text().toDouble());

        if(b_median)
            outliers_median=detector.locateOutliers(rawRRData_x,rawRRData_y,"median",ui->lineEdit_EctopicD_median->text().toDouble());
        qDebug()<<"2";
        QVector<double>Ectopic_x;//异常的x坐标
        QVector<double>Ectopic_y;//异常的y坐标
        for(int i=0;i<rawrr_Len;i++)
        {
            bool b=outliers_p.at(i)|| outliers_sd.at(i) || outliers_median.at(i);
            Ectopic_b.append(b);
            if(b)
            {
                Ectopic_x.append(rawRRData_x.at(i));
                Ectopic_y.append(rawRRData_y.at(i));
            }
        }
        qDebug()<<"Ectopic_x"<<Ectopic_x;
        ui->widget_RR->graph(3)->data().clear();
        if(!Ectopic_x.isEmpty()){
            ui->widget_RR->graph(3)->setData(Ectopic_x,Ectopic_y);
            ui->widget_RR->graph(3)->setPen(QPen(Qt::red,2));
        }
        else
            ui->widget_RR->graph(3)->setPen(QPen(Qt::blue,1));

    }else{
        ui->widget_RR->graph(3)->data().clear();
        ui->widget_RR->graph(3)->setPen(QPen(Qt::blue,1));
    }
    ui->widget_RR->replot();

}


void HRVAs::on_pc_replace_clicked()
{
    ui->pb_ectopicCheck->setEnabled(false);
    if(ui->radioButton_EctopicRep_None->isChecked())
    {
        //啥也不做
    }else if(ui->radioButton_EctopicRep_Mean->isChecked())
    {
        int meanv=ui->lineEdit_EctopicRep_mean->text().toInt();
        if(!Ectopic_b.isEmpty())
        {
            if(meanv>0)
            {
                // 创建 replaceOutliers 对象
                replaceOutliers processor(rawRRData_x, rawRRData_y, Ectopic_b);
                // 设置替换方法为均值替换，假设窗口大小为 3（即左右各取 1 个点）
                processor.setMethod("mean",  meanv);
                // 执行替换
                auto result = processor.execute();
                rawRRData_x.clear();rawRRData_y.clear();
                rawRRData_x=result.first;
                rawRRData_y=result.second;
                UpdateRRGraph(result.first,result.second);
            }else{
                QMessageBox::about(this,"温馨提示","均值窗口不能为空");
            }


        }
    }else if(ui->radioButton_EctopicRep_Median->isChecked())
    {
        int medianv=ui->lineEdit_EctopicRep_median->text().toInt();
        if(!Ectopic_b.isEmpty())
        {
            if(medianv>0)
            {
                // 创建 replaceOutliers 对象
                replaceOutliers processor(rawRRData_x, rawRRData_y, Ectopic_b);
                // 设置替换方法为中值替换，假设窗口大小为 3（即左右各取 1 个点）
                processor.setMethod("median",  medianv);
                // 执行替换
                auto result = processor.execute();
                rawRRData_x.clear();rawRRData_y.clear();
                rawRRData_x=result.first;
                rawRRData_y=result.second;
                UpdateRRGraph(result.first,result.second);
            }else{
                QMessageBox::about(this,"温馨提示","中值窗口不能为空");
            }
        }
    }else if(ui->radioButton_EctopicRep_Spline->isChecked())
    {
        if(!Ectopic_b.isEmpty())
        {
            // 创建 replaceOutliers 对象
            replaceOutliers processor(rawRRData_x, rawRRData_y, Ectopic_b);
            processor.setMethod("cubic");
            // 执行替换
            auto result = processor.execute();
            rawRRData_x.clear();rawRRData_y.clear();
            rawRRData_x=result.first;
            rawRRData_y=result.second;
            UpdateRRGraph(result.first,result.second);
        }
    }else if(ui->radioButton_EctopicRep_ReMove->isChecked())
    {
        if(!Ectopic_b.isEmpty())
        {
            // 创建 replaceOutliers 对象
            replaceOutliers processor(rawRRData_x, rawRRData_y, Ectopic_b);

            processor.setMethod("remove");
            // 执行替换
            auto result = processor.execute();
            rawRRData_x.clear();rawRRData_y.clear();
            rawRRData_x=result.first;
            rawRRData_y=result.second;
            qDebug()<<"rawRRData_x_size="<<rawRRData_x.size();
            qDebug()<<"rawRRData_x"<<rawRRData_x;
            UpdateRRGraph(result.first,result.second);
        }
    }
}


void HRVAs::on_pb_detrend_clicked()
{

}


void HRVAs::on_pushButton_startComp_clicked()
{
    HRV_TimeCompute timeCompute;
    double winLen=ui->lineEdit_SDNNi->text().toDouble();
    double pNNs=ui->lineEdit_pNNx->text().toDouble();
    HRV_TimeCompute::TimeDomainHRV tdh=timeCompute.timeDomainHRV(rawRRData_y,winLen,pNNs);
    ui->label_MeanRR->setText(QString::number(tdh.mean,'f',1));
    ui->label_MeanHR->setText(QString::number(tdh.meanHR,'f',1));
    ui->label_SDNN->setText(QString::number(tdh.SDNN,'f',1));
    ui->label_SDHR->setText(QString::number(tdh.sdHR,'f',1));
    ui->label_RMSSD->setText(QString::number(tdh.RMSSD,'f',1));
    ui->label_SDNNi->setText(QString::number(tdh.SDNNi,'f',1));
    ui->label_NNx->setText(QString::number(tdh.NNx,'f',1));
    ui->label_pNNx->setText(QString::number(tdh.pNNx,'f',1));

    ProHistogram_RR();
    ProHistogram_HR();
}

void HRVAs::ProHistogram_RR()
{
    double minVal, maxVal;
    ArrayOperation::instance().maximum(rawRRData_y,minVal,maxVal);
    int numBins = (maxVal - minVal)*1000/128;
    // 计算直方图
    auto histogramNum = histogram_RR.computeHistogram(rawRRData_y, numBins, minVal, maxVal);
    auto binEdges = histogram_RR.computeBinEdges(minVal, maxVal, numBins);
    // 绘制直方图
    histogram_RR.plotHistogram(ui->widget_RRHistogram, histogramNum, binEdges,"IBI Histogram","IBI(ms)","Counts");
}

void HRVAs::ProHistogram_HR()
{
    double minVal, maxVal;
    QVector<double>HrData;
    int len=rawRRData_y.size();
    for(int i=0;i<len;i++)
    {
        HrData.append(1000*60/rawRRData_y.at(i));
    }
    ArrayOperation::instance().maximum(HrData,minVal,maxVal);
    int numBins = (maxVal - minVal)*1000/128;
    // 计算直方图
    auto histogramNum = histogram_HR.computeHistogram(HrData, numBins, minVal, maxVal);
    auto binEdges = histogram_HR.computeBinEdges(minVal, maxVal, numBins);
    // 绘制直方图
    histogram_HR.plotHistogram(ui->widget_HRHistogram, histogramNum, binEdges,"HR Histogram","HR(bpm)","Counts");
}
